home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
ole2book.zip
/
CHAP11.ZIP
/
CHAP11
/
HSCHMOO
/
HSCHMOO.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-13
|
8KB
|
362 lines
/*
* HSCHMOO.CPP
* Handler for Schmoo, Chapter 11.
*
* DLL exports for an object handler as well as class factory.
*
* Copyright (c)1993 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Software Design Engineer
* Microsoft Systems Developer Relations
*
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#define INITGUIDS
#include "hschmoo.h"
//Count number of objects and number of locks.
ULONG g_cObj=0;
ULONG g_cLock=0;
//DLL Instance handle
HINSTANCE hgInst;
/*
* LibMain
*
* Purpose:
* DLL-specific entry point called from LibEntry.
*
* Parameters:
* hInst HINSTANCE instance of the DLL.
* wDataSeg WORD segment selector of the DLL's data segment.
* wHeapSize WORD byte count of the heap.
* lpCmdLine LPSTR to command line used to start the module.
*
* Return Value:
* HANDLE Instance handle of the DLL.
*
*/
HANDLE FAR PASCAL LibMain(HINSTANCE hInst, WORD wDataSeg
, WORD cbHeapSize, LPSTR lpCmdLine)
{
if (0!=cbHeapSize)
UnlockData(0);
hgInst=hInst;
return hInst;
}
/*
* WEP
*
* Purpose:
* Required DLL Exit function. Does nothing.
*
* Parameters:
* bSystemExit BOOL indicating if the system is being shut
* down or the DLL has just been unloaded.
*
* Return Value:
* void
*
*/
void FAR PASCAL WEP(int bSystemExit)
{
return;
}
/*
* DllGetClassObject
*
* Purpose:
* Provides an IClassFactory for a given CLSID that this DLL is
* registered to support. This DLL is placed under the CLSID
* in the registration database as the InProcServer.
*
* Parameters:
* clsID REFCLSID that identifies the class factory desired.
* Since this parameter is passed this DLL can handle
* any number of objects simply by returning different
* class factories here for different CLSIDs.
*
* riid REFIID specifying the interface the caller wants
* on the class object, usually IID_ClassFactory.
*
* ppv LPVOID FAR * in which to return the interface pointer.
*
* Return Value:
* HRESULT NOERROR on success, otherwise contains an error SCODE.
*/
HRESULT __export FAR PASCAL DllGetClassObject(REFCLSID rclsid, REFIID riid
, LPVOID FAR *ppv)
{
if (!IsEqualCLSID(rclsid, CLSID_Schmoo2Figure))
return ResultFromScode(E_FAIL);
//Check that we can provide the interface
if (!IsEqualIID(riid, IID_IUnknown) && !IsEqualIID(riid, IID_IClassFactory))
return ResultFromScode(E_NOINTERFACE);
//Return our IClassFactory for Figure objects
*ppv=(LPVOID)new CFigureClassFactory;
if (NULL==*ppv)
return ResultFromScode(E_OUTOFMEMORY);
//Don't forget to AddRef the object through any interface we return
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
/*
* DllCanUnloadNow
*
* Purpose:
* Answers if the DLL can be freed, that is, if there are no
* references to anything this DLL provides.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if nothing is using us, FALSE otherwise.
*/
STDAPI DllCanUnloadNow(void)
{
SCODE sc;
//Our answer is whether there are any object or locks
sc=(0L==g_cObj && 0==g_cLock) ? S_OK : S_FALSE;
return ResultFromScode(sc);
}
/*
* ObjectDestroyed
*
* Purpose:
* Function for the Figure object to call when it gets destroyed.
* Since we're in a DLL we only track the number of objects here
* letting DllCanUnloadNow take care of the rest.
*
* Parameters:
* None
*
* Return Value:
* None
*/
void FAR PASCAL ObjectDestroyed(void)
{
g_cObj--;
return;
}
/*
* CFigureClassFactory::CFigureClassFactory
*
* Purpose:
* Constructor for an object supporting an IClassFactory that
* instantiates Figure objects.
*
* Parameters:
* None
*/
CFigureClassFactory::CFigureClassFactory(void)
{
m_cRef =0L;
return;
}
/*
* CFigureClassFactory::~CFigureClassFactory
*
* Purpose:
* Destructor for a CFigureClassFactory object. This will be
* called when we ::Release the object to a zero reference count.
*/
CFigureClassFactory::~CFigureClassFactory(void)
{
return;
}
/*
* CFigureClassFactory::QueryInterface
* CFigureClassFactory::AddRef
* CFigureClassFactory::Release
*
* Purpose:
* IUnknown implementations for this object.
*/
STDMETHODIMP CFigureClassFactory::QueryInterface(REFIID riid, LPVOID FAR *ppv)
{
*ppv=NULL;
//Any interface on this object is the object pointer.
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
*ppv=(LPVOID)this;
/*
* If we actually assign an interface to ppv we need to AddRef it
* since we're returning a new pointer.
*/
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) CFigureClassFactory::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CFigureClassFactory::Release(void)
{
ULONG cRefT;
cRefT=--m_cRef;
if (0L==m_cRef)
delete this;
return cRefT;
}
/*
* CFigureClassFactory::CreateInstance
*
* Purpose:
* Instantiates a Figure object that supports the IFigure
* and IUnknown interfaces. If the caller asks for a different
* interface than these two then we fail.
*
* Parameters:
* punkOuter LPUNKNOWN to the controlling IUnknown if we are
* being used in an aggregation.
* riid REFIID identifying the interface the caller desires
* to have for the new object.
* ppvObj LPVOID FAR * in which to store the desired interface
* pointer for the new object.
*
* Return Value:
* HRESULT NOERROR if successful, otherwise contains E_NOINTERFACE
* if we cannot support the requested interface.
*/
STDMETHODIMP CFigureClassFactory::CreateInstance(LPUNKNOWN punkOuter
, REFIID riid, LPVOID FAR *ppvObj)
{
LPCFigure pObj;
HRESULT hr;
*ppvObj=NULL;
hr=ResultFromScode(E_OUTOFMEMORY);
//Verify that if there is a controlling unknown it's asking for IUnknown
if (NULL!=punkOuter && !IsEqualIID(riid, IID_IUnknown))
return ResultFromScode(E_NOINTERFACE);
//Create the object. This also creates a window.
pObj=new CFigure(punkOuter, ObjectDestroyed, hgInst);
if (NULL==pObj)
return hr;
if (pObj->FInit())
hr=pObj->QueryInterface(riid, ppvObj);
//Kill the object if initial creation or FInit failed.
if (FAILED(hr))
delete pObj;
else
g_cObj++;
return hr;
}
/*
* CFigureClassFactory::LockServer
*
* Purpose:
* Increments or decrements the lock count of the DLL. If the lock
* count goes to zero and there are no objects, the DLL is allowed
* to unload. See DllCanUnloadNow.
*
* Parameters:
* fLock BOOL specifying whether to increment or decrement the
* lock count.
*
* Return Value:
* HRESULT NOERROR always.
*/
STDMETHODIMP CFigureClassFactory::LockServer(BOOL fLock)
{
if (fLock)
g_cLock++;
else
g_cLock--;
return NOERROR;
}